<template>
  <div class="bom-add-page">
    <el-card class="bom-breadcrumb-card">
      <el-breadcrumb :separator-icon="ArrowRight">
        <el-breadcrumb-item :to="{ path: '/' }">物料管理</el-breadcrumb-item>
        <el-breadcrumb-item :to="{ path: '/BomList' }">BOM管理</el-breadcrumb-item>
        <el-breadcrumb-item>{{ isEdit ? "编辑BOM" : "新增BOM" }}</el-breadcrumb-item>
      </el-breadcrumb>
    </el-card>

    <el-card class="bom-main-card">
      <h2 class="bom-title">{{ isEdit ? "编辑BOM" : "新增BOM" }}</h2>

      <el-form ref="formRef" :model="formModel" :rules="rules" label-width="120px" class="bom-form">
        <el-row :gutter="24">
          <el-col :span="8">
            <el-form-item label="BOM编号" prop="bomcode">
              <el-input v-model="formModel.bomcode" placeholder="请输入BOM编号" :disabled="systemCodeAuto" />
            </el-form-item>
          </el-col>
          <el-col :span="4">
            <el-form-item label="系统编号">
              <el-switch v-model="systemCodeAuto" @change="handleAutoCodeChange" />
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="默认BOM">
              <el-radio-group v-model="formModel.bomstate">
                <el-radio :label="true">是</el-radio>
                <el-radio :label="false">否</el-radio>
              </el-radio-group>
            </el-form-item>
          </el-col>
        </el-row>

        <el-row :gutter="24">
          <el-col :span="12">
            <el-form-item label="产品" prop="productid">
              <el-input
                v-model="formModel.productname"
                placeholder="请选择产品"
                readonly
                @click="openRootProductDialog"
              >
                <template #suffix>
                  <el-icon><Search /></el-icon>
                </template>
              </el-input>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="产品编号">
              <el-input v-model="formModel.productcode" disabled />
            </el-form-item>
          </el-col>
        </el-row>

        <el-row :gutter="24">
          <el-col :span="10">
            <el-form-item label="规格型号">
              <el-input v-model="rootProductSnapshot.productmodelsame" disabled placeholder="自动填充" />
            </el-form-item>
          </el-col>
          <el-col :span="10">
            <el-form-item label="单位">
              <el-input v-model="rootProductSnapshot.productunit" disabled />
            </el-form-item>
          </el-col>
          <el-col :span="6">
            <el-form-item label="BOM版本">
              <el-input v-model="formModel.version" placeholder="请输入版本号" />
            </el-form-item>
          </el-col>
          <el-col :span="6">
            <el-form-item label="日产量">
              <el-input-number v-model="formModel.dailyOutput" :min="0" :precision="0" style="width: 100%" />
            </el-form-item>
          </el-col>
        </el-row>

        <el-form-item label="备注">
          <el-input v-model="formModel.bomdes" type="textarea" :rows="3" placeholder="请输入备注" />
        </el-form-item>
      </el-form>

      <section class="bom-section">
        <header class="section-header">
          <div>
            <span class="section-title">物料配件</span>
            <small v-if="currentParentName">当前父级：{{ currentParentName }}</small>
          </div>
          <div class="section-actions">
            <el-button type="primary" @click="openDetailSelector('product')" :disabled="!formModel.productid">添加子产品</el-button>
            <el-button type="primary" plain @click="openDetailSelector('material')" :disabled="!formModel.productid">添加物料</el-button>
          </div>
        </header>

        <el-table
          v-loading="detailLoading"
          :data="detailTableData"
          border
          row-key="nodekey"
          default-expand-all
          highlight-current-row
          :tree-props="{ children: 'children' }"
          @current-change="handleCurrentNodeChange"
        >
          <el-table-column label="节点类型" width="100">
            <template #default="{ row }">
              <el-tag v-if="row.isRoot" type="info">根产品</el-tag>
              <el-tag v-else :type="row.nodetype === 1 ? 'success' : 'warning'">
                {{ row.nodetype === 1 ? "产品" : "物料" }}
              </el-tag>
            </template>
          </el-table-column>
          <el-table-column prop="materialcode" label="编号" min-width="140" show-overflow-tooltip />
          <el-table-column prop="materialname" label="名称" min-width="160" show-overflow-tooltip />
          <el-table-column prop="specification" label="规格型号" min-width="140" show-overflow-tooltip />
          <el-table-column prop="unit" label="单位" width="80" />
          <el-table-column prop="quantity" label="使用量" width="120">
            <template #default="{ row }">
              <el-input-number
                v-model="row.quantity"
                :min="0"
                :precision="2"
                :disabled="row.isRoot"
                style="width: 100%"
              />
            </template>
          </el-table-column>
          <el-table-column prop="lossrate" label="使用比例(%)" width="140">
            <template #default="{ row }">
              <el-input-number
                v-model="row.lossrate"
                :min="0"
                :precision="2"
                :disabled="row.isRoot"
                style="width: 100%"
              />
            </template>
          </el-table-column>
          <el-table-column prop="remark" label="备注">
            <template #default="{ row }">
              <el-input v-model="row.remark" :disabled="row.isRoot" placeholder="请输入备注" />
            </template>
          </el-table-column>
          <el-table-column label="操作" width="140">
            <template #default="{ row }">
              <el-button
                v-if="!row.isRoot"
                type="primary"
                text
                size="small"
                @click.stop="setCurrentParent(row)"
              >
                设为父级
              </el-button>
              <el-divider v-if="!row.isRoot" direction="vertical" />
              <el-button
                v-if="!row.isRoot"
                type="danger"
                text
                size="small"
                @click.stop="handleRemoveNode(row)"
              >
                移除
              </el-button>
            </template>
          </el-table-column>
        </el-table>
      </section>

      <section class="bom-section">
        <header class="section-header">
          <div>
            <span class="section-title">工艺路线</span>
            <small v-if="selectedProcessRoute">当前选择：{{ selectedProcessRoute.process_routename }} ({{ selectedProcessRoute.process_routecode }})</small>
          </div>
          <el-button type="primary" @click="openProcessRouteDialog">选择工艺路线</el-button>
        </header>

        <el-empty v-if="!selectedProcessRoute" description="尚未选择工艺路线" />
        <el-descriptions v-else :column="2" border>
          <el-descriptions-item label="路线编号">{{ selectedProcessRoute.process_routecode }}</el-descriptions-item>
          <el-descriptions-item label="路线名称">{{ selectedProcessRoute.process_routename }}</el-descriptions-item>
          <el-descriptions-item label="状态">
            <el-tag :type="selectedProcessRoute.status === 1 ? 'success' : 'info'">
              {{ selectedProcessRoute.status === 1 ? "启用" : "停用" }}
            </el-tag>
          </el-descriptions-item>
          <el-descriptions-item label="备注">{{ selectedProcessRoute.remarks || "无" }}</el-descriptions-item>
        </el-descriptions>

        <template v-if="selectedProcessRoute">
          <div class="process-route-steps-wrapper">
            <div v-if="processStepsLoading" class="process-route-steps">
              <el-skeleton :rows="1" animated style="width: 100%" />
            </div>
            <div v-else-if="processSteps.length" class="process-route-steps">
              <div
                v-for="(step, index) in processSteps"
                :key="step.id || step.process_nodecode"
                class="process-route-step"
                :class="{ 'is-active': step.process_nodecode === activeProcessNodeCode }"
                @click="setActiveProcessNode(step)"
              >
                <span class="step-index">{{ index + 1 }}</span>
                <div class="step-meta">
                  <p class="step-name">{{ step.processname || `工序${index + 1}` }}</p>
                  <small class="step-desc">
                    {{ step.process_nodecode }}
                    <template v-if="step.nextprocessrelation && step.nextprocessname">
                      · {{ step.nextprocessrelation }} {{ step.nextprocessname }}
                    </template>
                  </small>
                </div>
              </div>
            </div>
            <el-empty v-else description="该工艺路线尚未配置工序节点" class="route-empty" />
          </div>

          <div class="process-route-filter-bar">
            <el-input v-model="routeMaterialFilter.keyword" placeholder="请输入物料编号/名称" clearable />
            <el-input v-model="routeMaterialFilter.unit" placeholder="请输入单位" clearable />
            <el-select v-model="routeMaterialFilter.materialType" placeholder="请选择物料类型" clearable>
              <el-option
                v-for="option in materialTypeOptions"
                :key="option.value"
                :label="option.label"
                :value="String(option.value)"
              />
            </el-select>
            <el-select v-model="routeMaterialFilter.materialAttribute" placeholder="请选择物料属性" clearable>
              <el-option
                v-for="option in materialAttributeOptions"
                :key="option.value"
                :label="option.label"
                :value="String(option.value)"
              />
            </el-select>
            <el-button @click="resetRouteMaterialFilter">重置</el-button>
          </div>

          <div class="process-route-table-card">
            <div class="process-route-toolbar">
              <el-button type="primary" @click="openProcessRouteMaterialSelector" :disabled="!processSteps.length">添加</el-button>
              <el-button
                type="danger"
                plain
                :disabled="!processRouteSelection.length"
                @click="removeSelectedProcessRouteMaterials"
              >
                移除
              </el-button>
            </div>
            <el-table
              :data="filteredProcessRouteMaterialRows"
              border
              stripe
              class="process-route-table"
              v-loading="processRouteMaterialsLoading"
              @selection-change="handleProcessRouteSelectionChange"
              height="360"
            >
              <el-table-column type="selection" width="48" />
              <el-table-column type="index" label="序号" width="70" />
              <el-table-column prop="materialcode" label="物料编号" min-width="140" show-overflow-tooltip />
              <el-table-column prop="materialname" label="物料名称" min-width="140" show-overflow-tooltip />
              <el-table-column prop="specification" label="规格型号" min-width="140" show-overflow-tooltip />
              <el-table-column prop="unit" label="单位" width="80" />
              <el-table-column label="物料类型" min-width="120">
                <template #default="{ row }">
                  {{ materialTypeMap[String(row.materialtypeid ?? "")] || "—" }}
                </template>
              </el-table-column>
              <el-table-column label="物料属性" min-width="120">
                <template #default="{ row }">
                  {{ materialAttributeMap[String(row.materialattributeid ?? "")] || "—" }}
                </template>
              </el-table-column>
              <el-table-column prop="quantity" label="使用量" width="120">
                <template #default="{ row }">
                  <el-input-number v-model="row.quantity" :min="0" :precision="2" :disabled="row.fromProcessRoute" style="width: 100%" />
                </template>
              </el-table-column>
              <el-table-column prop="lossrate" label="用料比例(%)" width="140">
                <template #default="{ row }">
                  <el-input-number v-model="row.lossrate" :min="0" :precision="2" :disabled="row.fromProcessRoute" style="width: 100%" />
                </template>
              </el-table-column>
              <el-table-column label="操作" width="160">
                <template #default="{ row }">
                  <el-button
                    v-if="row.fromProcessRoute"
                    type="primary"
                    link
                    size="small"
                    @click="openProcessRouteMaterialEdit(row)"
                  >
                    编辑
                  </el-button>
                  <el-divider v-if="row.fromProcessRoute" direction="vertical" />
                  <el-button type="danger" link size="small" @click="removeSelectedProcessRouteMaterials([row])">
                    移除
                  </el-button>
                </template>
              </el-table-column>
            </el-table>
          </div>
        </template>
      </section>

      <div class="footer-actions">
        <el-button @click="handleClose">关闭</el-button>
        <el-button type="primary" :loading="submitting" @click="handleSubmit">确定</el-button>
      </div>
    </el-card>

    <!-- 根产品选择 -->
    <el-dialog v-model="productDialogVisible" title="选择产品" width="960px">
      <el-form :model="productQueryForm" inline class="dialog-filter">
        <el-form-item label="产品编号/名称">
          <el-input v-model="productQueryForm.productname" placeholder="请输入关键字" clearable @keyup.enter="handleProductQuery" />
        </el-form-item>
        <el-form-item label="类型">
          <el-select v-model="productQueryForm.productType" placeholder="请选择" clearable>
            <el-option v-for="item in productTypeOptions" :key="item.value" :label="item.label" :value="item.value" />
          </el-select>
        </el-form-item>
        <el-form-item label="属性">
          <el-select v-model="productQueryForm.productAttribute" placeholder="请选择" clearable>
            <el-option v-for="item in productAttributeOptions" :key="item.value" :label="item.label" :value="item.value" />
          </el-select>
        </el-form-item>
        <el-form-item>
          <el-button type="primary" @click="handleProductQuery">查询</el-button>
          <el-button @click="handleProductReset">重置</el-button>
        </el-form-item>
      </el-form>
      <el-table :data="productTableData" border stripe highlight-current-row @row-click="handleProductRowClick">
        <el-table-column type="index" width="60" label="序号" />
        <el-table-column label="选择" width="80" align="center">
          <template #default="{ row }">
            <el-radio :model-value="selectedProductId" :label="row.id" @change="handleProductSelect(row)" />
          </template>
        </el-table-column>
        <el-table-column prop="productcard" label="产品编号" min-width="120" />
        <el-table-column prop="productname" label="产品名称" min-width="140" />
        <el-table-column prop="productmodelsame" label="规格型号" min-width="140" />
        <el-table-column prop="productunit" label="单位" width="80" />
        <el-table-column prop="productTypeLabel" label="类型" width="100" />
        <el-table-column prop="productAttributeLabel" label="属性" width="100" />
      </el-table>
      <el-pagination
        v-model:current-page="productPagination.pageIndex"
        v-model:page-size="productPagination.pageSize"
        :page-sizes="[10, 20, 30]"
        background
        layout="total, sizes, prev, pager, next"
        :total="productPagination.totalCount"
        @size-change="handleProductSizeChange"
        @current-change="handleProductCurrentChange"
        style="margin-top: 12px"
      />
      <template #footer>
        <el-button @click="productDialogVisible = false">取消</el-button>
        <el-button type="primary" @click="handleConfirmProduct">确定</el-button>
      </template>
    </el-dialog>

    <!-- 明细选择弹窗 -->
    <el-dialog v-model="detailSelectorVisible" title="添加明细" width="1000px">
      <el-tabs v-model="detailSelectorTab" @tab-click="handleDetailTabChange">
        <el-tab-pane label="物料" name="material">
          <el-form :model="materialQueryForm" inline class="dialog-filter">
            <el-form-item label="物料编号/名称">
              <el-input v-model="materialQueryForm.materialname" placeholder="请输入关键字" clearable @keyup.enter="handleMaterialQuery" />
            </el-form-item>
            <el-form-item>
              <el-button type="primary" @click="handleMaterialQuery">查询</el-button>
              <el-button @click="handleMaterialReset">重置</el-button>
            </el-form-item>
          </el-form>
          <el-table
            :data="materialTableData"
            border
            stripe
            @selection-change="handleMaterialSelectionChange"
            height="360"
          >
            <el-table-column type="selection" width="50" />
            <el-table-column type="index" width="60" />
            <el-table-column prop="materialcode" label="物料编号" min-width="130" />
            <el-table-column prop="materialname" label="物料名称" min-width="130" />
            <el-table-column prop="specification" label="规格型号" min-width="130" />
            <el-table-column prop="unit" label="单位" width="80" />
          </el-table>
          <el-pagination
            v-model:current-page="materialPagination.pageIndex"
            v-model:page-size="materialPagination.pageSize"
            :page-sizes="[10, 20, 30]"
            background
            layout="total, sizes, prev, pager, next"
            :total="materialPagination.totalCount"
            @size-change="handleMaterialSizeChange"
            @current-change="handleMaterialCurrentChange"
            style="margin-top: 12px"
          />
        </el-tab-pane>
        <el-tab-pane label="产品" name="product">
          <el-form :model="detailProductQueryForm" inline class="dialog-filter">
            <el-form-item label="产品编号/名称">
              <el-input v-model="detailProductQueryForm.productname" placeholder="请输入关键字" clearable @keyup.enter="handleDetailProductQuery" />
            </el-form-item>
            <el-form-item>
              <el-button type="primary" @click="handleDetailProductQuery">查询</el-button>
              <el-button @click="handleDetailProductReset">重置</el-button>
            </el-form-item>
          </el-form>
          <el-table
            :data="detailProductTableData"
            border
            stripe
            @selection-change="handleDetailProductSelectionChange"
            height="360"
          >
            <el-table-column type="selection" width="50" />
            <el-table-column type="index" width="60" />
            <el-table-column prop="productcard" label="产品编号" min-width="130" />
            <el-table-column prop="productname" label="产品名称" min-width="130" />
            <el-table-column prop="productmodelsame" label="规格型号" min-width="130" />
            <el-table-column prop="productunit" label="单位" width="80" />
          </el-table>
          <el-pagination
            v-model:current-page="detailProductPagination.pageIndex"
            v-model:page-size="detailProductPagination.pageSize"
            :page-sizes="[10, 20, 30]"
            background
            layout="total, sizes, prev, pager, next"
            :total="detailProductPagination.totalCount"
            @size-change="handleDetailProductSizeChange"
            @current-change="handleDetailProductCurrentChange"
            style="margin-top: 12px"
          />
        </el-tab-pane>
      </el-tabs>
      <template #footer>
        <el-button @click="detailSelectorVisible = false">取消</el-button>
        <el-button type="primary" @click="handleConfirmDetailSelection">确定</el-button>
      </template>
    </el-dialog>

    <!-- 工艺路线选择 -->
    <el-dialog v-model="processRouteDialogVisible" title="选择工艺路线" width="900px">
      <el-form :model="processRouteQuery" inline class="dialog-filter">
        <el-form-item label="编号/名称">
          <el-input v-model="processRouteQuery.keyword" placeholder="请输入" clearable @keyup.enter="fetchProcessRouteList" />
        </el-form-item>
        <el-form-item label="状态">
          <el-select v-model="processRouteQuery.status" placeholder="请选择" clearable>
            <el-option label="全部" :value="0" />
            <el-option label="启用" :value="1" />
            <el-option label="停用" :value="2" />
          </el-select>
        </el-form-item>
        <el-form-item>
          <el-button type="primary" @click="fetchProcessRouteList">查询</el-button>
          <el-button @click="resetProcessRouteQuery">重置</el-button>
        </el-form-item>
      </el-form>
      <el-table
        :data="processRouteRows"
        border
        stripe
        @row-click="(row:any) => (selectedProcessRouteId = row.id)"
        height="360"
      >
        <el-table-column type="index" width="60" />
        <el-table-column label="选择" width="80" align="center">
          <template #default="{ row }">
            <el-radio :model-value="selectedProcessRouteId" :label="row.id" />
          </template>
        </el-table-column>
        <el-table-column prop="process_routecode" label="路线编号" min-width="160" />
        <el-table-column prop="process_routename" label="路线名称" min-width="160" />
        <el-table-column label="状态" width="100">
          <template #default="{ row }">
            <el-tag :type="row.status === 1 ? 'success' : 'info'">{{ row.status === 1 ? "启用" : "停用" }}</el-tag>
          </template>
        </el-table-column>
        <el-table-column prop="description" label="说明" min-width="180" show-overflow-tooltip />
      </el-table>
      <el-pagination
        v-model:current-page="processRoutePager.page"
        v-model:page-size="processRoutePager.size"
        :page-sizes="[10, 20, 50]"
        background
        layout="total, sizes, prev, pager, next"
        :total="processRoutePager.total"
        @size-change="handleProcessRouteSizeChange"
        @current-change="handleProcessRoutePageChange"
        style="margin-top: 12px"
      />
      <template #footer>
        <el-button @click="processRouteDialogVisible = false">取消</el-button>
        <el-button type="primary" @click="handleConfirmProcessRoute">确定</el-button>
      </template>
    </el-dialog>

    <!-- 工序物料编辑 -->
    <el-dialog v-model="processRouteMaterialEdit.visible" title="编辑" width="460px">
      <el-form label-width="90px" class="dialog-filter">
        <el-form-item label="物料编号">
          <el-input v-model="processRouteMaterialEdit.form.materialcode" disabled />
        </el-form-item>
        <el-form-item label="物料名称">
          <el-input v-model="processRouteMaterialEdit.form.materialname" disabled />
        </el-form-item>
        <el-form-item label="规格型号">
          <el-input v-model="processRouteMaterialEdit.form.specification" disabled />
        </el-form-item>
        <el-form-item label="单位">
          <el-input v-model="processRouteMaterialEdit.form.unit" disabled />
        </el-form-item>
        <el-form-item label="使用量" required>
          <el-input-number v-model="processRouteMaterialEdit.form.usagequantity" :min="0" :precision="2" style="width: 100%" />
        </el-form-item>
        <el-form-item label="用料比例" required>
          <el-input-number v-model="processRouteMaterialEdit.form.proportion" :min="0" :precision="2" style="width: 100%" />
        </el-form-item>
      </el-form>
      <template #footer>
        <el-button @click="processRouteMaterialEdit.visible = false">取消</el-button>
        <el-button type="primary" :loading="processRouteMaterialEdit.loading" @click="submitProcessRouteMaterialEdit">确定</el-button>
      </template>
    </el-dialog>
  </div>
</template>

<script lang="ts" setup>
import { ArrowRight, Search } from "@element-plus/icons-vue";
import https from "@/Http/http";
import { ElMessage, ElMessageBox, type FormInstance, type FormRules } from "element-plus";
import { computed, onMounted, reactive, ref, watch } from "vue";
import { useRoute, useRouter } from "vue-router";

interface BomDetailItem {
  id?: number;
  materialid: number;
  materialcode: string;
  materialname: string;
  specification: string;
  unit: string;
  quantity: number;
  lossrate: number;
  sortorder: number;
  remark: string;
  nodetype: number;
  nodekey: string;
  parentnodekey: string;
  isRoot?: boolean;
  children?: BomDetailItem[];
  materialtypeid?: number | null;
  materialattributeid?: number | null;
  fromProcessRoute?: boolean;
  processNodeCode?: string | null;
  processNodeId?: number | null;
  processRouteCode?: string | null;
}

interface ProcessNode {
  id: number;
  process_routecode: string;
  process_nodecode: string;
  processname?: string;
  nextprocessname?: string;
  nextprocessrelation?: string;
  iskeyprocess?: boolean;
}

const ROOT_NODE_KEY = "ROOT";

const router = useRouter();
const route = useRoute();
const formRef = ref<FormInstance>();
const submitting = ref(false);
const isEdit = ref(false);
const bomId = ref<number>(0);
const systemCodeAuto = ref(true);

const formModel = reactive({
  bomcode: "",
  bomname: "",
  productid: null as number | null,
  productcode: "",
  productname: "",
  version: "",
  bomstate: true,
  bomdes: "",
  dailyOutput: 0,
  process_routeid: 0,
});

const rootProductSnapshot = reactive({
  id: 0,
  productmodelsame: "",
  productunit: "",
});

const detailFlatList = ref<BomDetailItem[]>([]);
const detailLoading = ref(false);
const currentParentNodeKey = ref(ROOT_NODE_KEY);

const currentParentName = computed(() => {
  if (currentParentNodeKey.value === ROOT_NODE_KEY) {
    return formModel.productname || "根节点";
  }
  const hit = detailFlatList.value.find((item) => item.nodekey === currentParentNodeKey.value);
  return hit?.materialname;
});

const buildDetailTree = computed(() => {
  const map = new Map<string, BomDetailItem>();
  detailFlatList.value.forEach((item) => {
    item.children = [];
    map.set(item.nodekey, item);
  });
  const roots: BomDetailItem[] = [];
  map.forEach((node) => {
    if (node.parentnodekey === ROOT_NODE_KEY) {
      roots.push(node);
    } else {
      const parent = map.get(node.parentnodekey);
      if (parent) {
        parent.children?.push(node);
      }
    }
  });
  return roots;
});

const detailTableData = computed(() => {
  if (!formModel.productid) {
    return [];
  }
  return [
    {
      materialid: formModel.productid,
      materialcode: formModel.productcode,
      materialname: formModel.productname,
      specification: rootProductSnapshot.productmodelsame,
      unit: rootProductSnapshot.productunit,
      quantity: formModel.dailyOutput || 0,
      lossrate: 0,
      sortorder: 0,
      remark: "",
      nodetype: 1,
      nodekey: ROOT_NODE_KEY,
      parentnodekey: "",
      isRoot: true,
      children: buildDetailTree.value,
    } as BomDetailItem,
  ];
});

const processRouteMaterialRows = computed(() => {
  const activeId = activeProcessNodeId.value;
  const rows = detailFlatList.value
    .filter(item => item.fromProcessRoute)
    .sort((a, b) => (a.sortorder || 0) - (b.sortorder || 0));
  if (!activeId) {
    return rows;
  }
  return rows.filter(item => !item.processNodeId || item.processNodeId === activeId);
});

const filteredProcessRouteMaterialRows = computed(() => {
  const keyword = routeMaterialFilter.keyword.trim().toLowerCase();
  const unit = routeMaterialFilter.unit.trim().toLowerCase();
  const typeFilter = routeMaterialFilter.materialType;
  const attributeFilter = routeMaterialFilter.materialAttribute;
  return processRouteMaterialRows.value.filter(item => {
    const matchesKeyword =
      !keyword ||
      [item.materialcode, item.materialname, item.specification]
        .filter(field => typeof field === "string" && field)
        .some(field => (field as string).toLowerCase().includes(keyword));
    const matchesUnit = !unit || (item.unit || "").toLowerCase().includes(unit);
    const matchesType = !typeFilter || String(item.materialtypeid ?? "") === typeFilter;
    const matchesAttribute =
      !attributeFilter || String(item.materialattributeid ?? "") === attributeFilter;
    return matchesKeyword && matchesUnit && matchesType && matchesAttribute;
  });
});

const detailSelectorVisible = ref(false);
const detailSelectorTab = ref<"material" | "product">("material");
const materialTableData = ref<any[]>([]);
const materialSelection = ref<any[]>([]);
const materialPagination = reactive({
  pageIndex: 1,
  pageSize: 10,
  totalCount: 0,
});
const materialQueryForm = reactive({
  materialname: "",
});

const detailProductTableData = ref<any[]>([]);
const detailProductSelection = ref<any[]>([]);
const handleMaterialSelectionChange = (rows: any[]) => {
  materialSelection.value = rows;
};

const processRouteMaterialEdit = reactive({
  visible: false,
  loading: false,
  form: {
    id: 0,
    materialcode: "",
    materialname: "",
    specification: "",
    unit: "",
    usagequantity: 0,
    proportion: 0
  }
});

const handleDetailProductSelectionChange = (rows: any[]) => {
  detailProductSelection.value = rows;
};
const detailProductPagination = reactive({
  pageIndex: 1,
  pageSize: 10,
  totalCount: 0,
});
const detailProductQueryForm = reactive({
  productname: "",
});

const productDialogVisible = ref(false);
const productTableData = ref<any[]>([]);
const selectedProductId = ref<number | null>(null);
const selectedProductRow = ref<any>(null);
const productPagination = reactive({
  pageIndex: 1,
  pageSize: 10,
  totalCount: 0,
});
const productQueryForm = reactive({
  productname: "",
  productType: null as number | null,
  productAttribute: null as number | null,
});

const productTypeOptions = [
  { label: "类型一", value: 1 },
  { label: "类型二", value: 2 },
  { label: "类型三", value: 3 },
];

const productAttributeOptions = [
  { label: "自制", value: 1 },
  { label: "外购", value: 2 },
];

const materialTypeOptions = [
  { label: "生产物料", value: 1 },
  { label: "辅助物料", value: 2 },
  { label: "耗材", value: 3 }
];

const materialAttributeOptions = [
  { label: "采购", value: 1 },
  { label: "自制", value: 2 },
  { label: "委外", value: 3 }
];

const materialTypeMap = computed(() => {
  return materialTypeOptions.reduce<Record<string, string>>((acc, cur) => {
    acc[String(cur.value)] = cur.label;
    return acc;
  }, {});
});

const materialAttributeMap = computed(() => {
  return materialAttributeOptions.reduce<Record<string, string>>((acc, cur) => {
    acc[String(cur.value)] = cur.label;
    return acc;
  }, {});
});

const processRouteDialogVisible = ref(false);
const processRouteRows = ref<any[]>([]);
const processRoutePager = reactive({
  page: 1,
  size: 10,
  total: 0,
});
const processRouteQuery = reactive({
  keyword: "",
  status: 0,
});
const selectedProcessRouteId = ref<number | null>(null);
const selectedProcessRoute = ref<any>(null);
const processSteps = ref<ProcessNode[]>([]);
const processStepsLoading = ref(false);
const activeProcessNodeCode = ref<string>("");
const activeProcessNodeId = ref<number | null>(null);
const processRouteMaterialsLoading = ref(false);
const processRouteSelection = ref<BomDetailItem[]>([]);
const detailSelectorContext = ref<"bom" | "route">("bom");
const routeMaterialFilter = reactive({
  keyword: "",
  unit: "",
  materialType: "",
  materialAttribute: ""
});

const resetRouteMaterialFilter = () => {
  routeMaterialFilter.keyword = "";
  routeMaterialFilter.unit = "";
  routeMaterialFilter.materialType = "";
  routeMaterialFilter.materialAttribute = "";
};

const rules = reactive<FormRules>({
  bomcode: [{ required: true, message: "请输入BOM编号", trigger: "blur" }],
  bomname: [{ required: true, message: "请输入BOM名称", trigger: "blur" }],
  productid: [{ required: true, message: "请选择产品", trigger: "change" }],
});

const createNodeKey = () => `NODE_${Date.now()}_${Math.random().toString(16).slice(2, 8)}`;

const handleAutoCodeChange = (val: boolean) => {
  if (val) {
    formModel.bomcode = generateAutoCode();
  }
};

const generateAutoCode = () => {
  const now = new Date();
  const y = now.getFullYear();
  const m = `${now.getMonth() + 1}`.padStart(2, "0");
  const d = `${now.getDate()}`.padStart(2, "0");
  const t = `${now.getHours()}${now.getMinutes()}${now.getSeconds()}`;
  return `BOM${y}${m}${d}${t}`;
};

const openRootProductDialog = () => {
  handleProductQuery();
  productDialogVisible.value = true;
};

const handleProductQuery = async () => {
  const params: Record<string, any> = {
    pageindex: productPagination.pageIndex,
    pagesize: productPagination.pageSize,
  };
  if (productQueryForm.productname) params.productname = productQueryForm.productname;
  if (productQueryForm.productType !== null) params.producttypeid = productQueryForm.productType;
  if (productQueryForm.productAttribute !== null) params.productattributeid = productQueryForm.productAttribute;
  const { data } = await https.Reads.get("/Product/ProductGetList", { params });
  if (data.code === 1) {
    productTableData.value = (data.data || []).map((item: any) => ({
      ...item,
      productTypeLabel: productTypeOptions.find((x) => x.value === item.producttypeid)?.label || "--",
      productAttributeLabel: productAttributeOptions.find((x) => x.value === item.productattributeid)?.label || "--",
    }));
    productPagination.totalCount = data.totalCount || productTableData.value.length;
  }
};

const handleProductReset = () => {
  productQueryForm.productname = "";
  productQueryForm.productType = null;
  productQueryForm.productAttribute = null;
  handleProductQuery();
};

const handleProductSizeChange = (size: number) => {
  productPagination.pageSize = size;
  productPagination.pageIndex = 1;
  handleProductQuery();
};

const handleProductCurrentChange = (page: number) => {
  productPagination.pageIndex = page;
  handleProductQuery();
};

const handleProductRowClick = (row: any) => {
  selectedProductId.value = row.id;
  selectedProductRow.value = row;
};

const handleProductSelect = (row: any) => {
  selectedProductId.value = row.id;
  selectedProductRow.value = row;
};

const handleConfirmProduct = () => {
  if (!selectedProductRow.value) {
    ElMessage.warning("请选择产品");
    return;
  }
  formModel.productid = selectedProductRow.value.id;
  formModel.productcode = selectedProductRow.value.productcard;
  formModel.productname = selectedProductRow.value.productname;
  rootProductSnapshot.id = selectedProductRow.value.id;
  rootProductSnapshot.productmodelsame = selectedProductRow.value.productmodelsame || "";
  rootProductSnapshot.productunit = selectedProductRow.value.productunit || "";
  detailFlatList.value = detailFlatList.value.map((item) => item); // 保持数据
  currentParentNodeKey.value = ROOT_NODE_KEY;
  productDialogVisible.value = false;
};

const openDetailSelector = (type: "material" | "product", context: "bom" | "route" = "bom") => {
  if (!formModel.productid) {
    ElMessage.warning("请先选择BOM对应的产品");
    return;
  }
  detailSelectorContext.value = context;
  detailSelectorTab.value = type;
  if (type === "material") {
    handleMaterialQuery();
  } else {
    handleDetailProductQuery();
  }
  detailSelectorVisible.value = true;
};

const handleDetailTabChange = (pane: any) => {
  if (pane.paneName === "material") {
    handleMaterialQuery();
  } else {
    handleDetailProductQuery();
  }
};

const handleMaterialQuery = async () => {
  const params: Record<string, any> = {
    pageindex: materialPagination.pageIndex,
    pagesize: materialPagination.pageSize,
  };
  if (materialQueryForm.materialname) params.materialname = materialQueryForm.materialname;
  const { data } = await https.Reads.get("/Material/MaterialGetList", { params });
  if (data.code === 1) {
    materialTableData.value = (data.data || []).map((item: any) => ({
      materialid: item.id,
      materialcode: item.materialcard,
      materialname: item.materialname,
      specification: item.materialmodelsame,
      unit: item.materialunit,
      materialtypeid: item.materialtypeid,
      materialattributeid: item.materialattributeid,
    }));
    materialPagination.totalCount = data.totalCount || materialTableData.value.length;
  }
};

const handleMaterialReset = () => {
  materialQueryForm.materialname = "";
  handleMaterialQuery();
};

const handleMaterialSizeChange = (size: number) => {
  materialPagination.pageSize = size;
  materialPagination.pageIndex = 1;
  handleMaterialQuery();
};

const handleMaterialCurrentChange = (page: number) => {
  materialPagination.pageIndex = page;
  handleMaterialQuery();
};

const handleDetailProductQuery = async () => {
  const params: Record<string, any> = {
    pageindex: detailProductPagination.pageIndex,
    pagesize: detailProductPagination.pageSize,
  };
  if (detailProductQueryForm.productname) params.productname = detailProductQueryForm.productname;
  const { data } = await https.Reads.get("/Product/ProductGetList", { params });
  if (data.code === 1) {
    detailProductTableData.value = data.data || [];
    detailProductPagination.totalCount = data.totalCount || detailProductTableData.value.length;
  }
};

const handleDetailProductReset = () => {
  detailProductQueryForm.productname = "";
  handleDetailProductQuery();
};

const handleDetailProductSizeChange = (size: number) => {
  detailProductPagination.pageSize = size;
  detailProductPagination.pageIndex = 1;
  handleDetailProductQuery();
};

const handleDetailProductCurrentChange = (page: number) => {
  detailProductPagination.pageIndex = page;
  handleDetailProductQuery();
};

const handleConfirmDetailSelection = async () => {
  const context = detailSelectorContext.value;
  const parentKey = currentParentNodeKey.value || ROOT_NODE_KEY;
  const targetArray = detailSelectorTab.value === "material" ? materialSelection.value : detailProductSelection.value;
  if (!targetArray.length) {
    ElMessage.warning("请至少选择一条数据");
    return;
  }

  if (context === "route") {
    if (!activeProcessNodeId.value) {
      ElMessage.warning("请选择工序节点");
      return;
    }
    const materialIds = targetArray
      .map((row: any) => row.materialid || row.id)
      .filter((id: number | undefined) => !!id);
    if (!materialIds.length) {
      ElMessage.warning("请选择有效的物料");
      return;
    }
    try {
      const { data } = await https.Writes.post("/AProcess_route/OperationMaterialsBatchAdd", {
        operation_routeid: activeProcessNodeId.value,
        materialIds
      });
      if (data?.code === 1 || data?.Code === 1) {
        ElMessage.success(data?.msg || data?.Msg || "添加工序物料成功");
        await fetchProcessRouteMaterials(selectedProcessRoute.value?.process_routecode || "");
        detailSelectorVisible.value = false;
        materialSelection.value = [];
        detailProductSelection.value = [];
      } else {
        throw new Error(data?.msg || data?.Msg || "添加工序物料失败");
      }
    } catch (error: any) {
      console.error("operation materials add failed", error);
      ElMessage.error(error?.message || "添加工序物料失败");
    }
    return;
  }

  targetArray.forEach((row: any) => {
    const node: BomDetailItem = {
      materialid: row.materialid || row.id,
      materialcode: row.materialcode || row.productcard,
      materialname: row.materialname || row.productname,
      specification: row.specification || row.productmodelsame || "",
      unit: row.unit || row.productunit || "",
      quantity: 1,
      lossrate: 0,
      sortorder: detailFlatList.value.length + 1,
      remark: "",
      nodetype: detailSelectorTab.value === "material" ? 2 : 1,
      nodekey: createNodeKey(),
      parentnodekey: parentKey,
      materialtypeid: row.materialtypeid || null,
      materialattributeid: row.materialattributeid || null,
      fromProcessRoute: false,
      processNodeCode: null,
      processNodeId: null,
      processRouteCode: null
    };
    detailFlatList.value.push(node);
  });
  updateSortOrder();
  detailSelectorVisible.value = false;
  materialSelection.value = [];
  detailProductSelection.value = [];
};

const fetchProcessSteps = async (routeCode: string) => {
  if (!routeCode) {
    processSteps.value = [];
    activeProcessNodeCode.value = "";
    activeProcessNodeId.value = null;
    return;
  }
  processStepsLoading.value = true;
  try {
    const { data } = await https.Reads.get("/AManufacturing_process/GetProcessComposition", {
      params: { process_routecode: routeCode }
    });
    if (data?.code === 1 || data?.Code === 1) {
      processSteps.value = data.data || data.Data || [];
      activeProcessNodeCode.value = processSteps.value[0]?.process_nodecode || "";
      activeProcessNodeId.value = processSteps.value[0]?.id ?? null;
    } else {
      processSteps.value = [];
      activeProcessNodeCode.value = "";
      activeProcessNodeId.value = null;
    }
  } catch (error) {
    console.error("fetch process steps error", error);
    processSteps.value = [];
    activeProcessNodeCode.value = "";
    activeProcessNodeId.value = null;
    ElMessage.error("获取工艺路线节点失败");
  } finally {
    processStepsLoading.value = false;
  }
};

const applyProcessRouteMaterials = (rows: any[]) => {
  detailFlatList.value = detailFlatList.value.filter(item => !item.fromProcessRoute);
  if (!rows || !rows.length) {
    return;
  }
  const routeCode = selectedProcessRoute.value?.process_routecode || "";
  const baseIndex = detailFlatList.value.length;
  const converted = rows.map((item, index) => ({
    id: item.id,
    materialid: item.related_materialsid || item.materialid,
    materialcode: item.materialcode || item.materialCard || "",
    materialname: item.materialname || item.materialName || "",
    specification: item.specification || item.materialmodelsame || "",
    unit: item.unit || item.materialunit || "",
    quantity: Number(item.usagequantity ?? item.quantity ?? 1),
    lossrate: Number(item.proportion ?? item.lossrate ?? 0),
    sortorder: baseIndex + index + 1,
    remark: item.remark || "",
    nodetype: 2,
    nodekey: createNodeKey(),
    parentnodekey: ROOT_NODE_KEY,
    materialtypeid: item.materialtypeid ?? item.materialTypeId ?? null,
    materialattributeid: item.materialattributeid ?? item.materialAttributeId ?? null,
    fromProcessRoute: true,
    processNodeCode: item.process_nodecode || item.processNodeCode || null,
    processNodeId: item.operation_routeid || item.processNodeId || null,
    processRouteCode: routeCode
  })) as BomDetailItem[];
  detailFlatList.value = detailFlatList.value.concat(converted);
  updateSortOrder();
};

const fetchProcessRouteMaterials = async (routeCode: string) => {
  if (!routeCode) {
    applyProcessRouteMaterials([]);
    return;
  }
  processRouteMaterialsLoading.value = true;
  try {
    const { data } = await https.Reads.get("/AManufacturing_process/GetOperationMaterials", {
      params: { process_routecode: routeCode }
    });
    if (data?.code === 1 || data?.Code === 1) {
      applyProcessRouteMaterials(data.data || data.Data || []);
    } else {
      applyProcessRouteMaterials([]);
    }
  } catch (error) {
    console.error("fetch process route materials error", error);
    applyProcessRouteMaterials([]);
    ElMessage.error("获取工艺路线物料失败");
  } finally {
    processRouteMaterialsLoading.value = false;
  }
};

const clearProcessRouteMaterials = () => {
  detailFlatList.value = detailFlatList.value.filter(item => !item.fromProcessRoute);
};

const handleProcessRouteSelectionChange = (rows: BomDetailItem[]) => {
  processRouteSelection.value = rows;
};

const openProcessRouteMaterialEdit = (row: BomDetailItem) => {
  if (!row.fromProcessRoute || !row.id) {
    ElMessage.warning("仅支持编辑工序同步的物料");
    return;
  }
  processRouteMaterialEdit.form.id = Number(row.id);
  processRouteMaterialEdit.form.materialcode = row.materialcode || "";
  processRouteMaterialEdit.form.materialname = row.materialname || "";
  processRouteMaterialEdit.form.specification = row.specification || "";
  processRouteMaterialEdit.form.unit = row.unit || "";
  processRouteMaterialEdit.form.usagequantity = Number(row.quantity || 0);
  processRouteMaterialEdit.form.proportion = Number(row.lossrate || 0);
  processRouteMaterialEdit.visible = true;
};

const submitProcessRouteMaterialEdit = async () => {
  if (!processRouteMaterialEdit.form.id) {
    ElMessage.warning("记录ID无效");
    return;
  }
  processRouteMaterialEdit.loading = true;
  try {
    const { data } = await https.Writes.post("/AProcess_route/OperationMaterialsUpdate", {
      id: processRouteMaterialEdit.form.id,
      usagequantity: processRouteMaterialEdit.form.usagequantity,
      proportion: processRouteMaterialEdit.form.proportion
    });
    if (data?.code === 1 || data?.Code === 1) {
      ElMessage.success(data?.msg || data?.Msg || "更新成功");
      processRouteMaterialEdit.visible = false;
      await fetchProcessRouteMaterials(selectedProcessRoute.value?.process_routecode || "");
    } else {
      throw new Error(data?.msg || data?.Msg || "更新失败");
    }
  } catch (error: any) {
    console.error("update operation material failed", error);
    ElMessage.error(error?.message || "更新失败");
  } finally {
    processRouteMaterialEdit.loading = false;
  }
};

const removeSelectedProcessRouteMaterials = (rows?: BomDetailItem[]) => {
  const targets = rows && rows.length ? rows : processRouteSelection.value;
  if (!targets.length) {
    ElMessage.warning("请选择需要移除的物料");
    return;
  }
  if (targets.some(item => item.fromProcessRoute)) {
    ElMessage.info("工序物料请在工艺路线页面删除");
    return;
  }
  const removeKeys = new Set(targets.map(item => item.nodekey));
  detailFlatList.value = detailFlatList.value.filter(item => !removeKeys.has(item.nodekey));
  processRouteSelection.value = [];
  updateSortOrder();
};

const openProcessRouteMaterialSelector = () => {
  if (!selectedProcessRoute.value?.process_routecode) {
    ElMessage.warning("请先选择工艺路线");
    return;
  }
  const targetNode = activeProcessNodeCode.value || processSteps.value[0]?.process_nodecode;
  const targetNodeId = activeProcessNodeId.value || processSteps.value[0]?.id || null;
  if (!targetNode || !targetNodeId) {
    ElMessage.warning("当前工艺路线尚未配置工序节点");
    return;
  }
  activeProcessNodeCode.value = targetNode;
  activeProcessNodeId.value = targetNodeId;
  detailSelectorTab.value = "material";
  detailSelectorContext.value = "route";
  handleMaterialQuery();
  detailSelectorVisible.value = true;
};

const setActiveProcessNode = (node: ProcessNode) => {
  activeProcessNodeCode.value = node.process_nodecode;
  activeProcessNodeId.value = node.id;
};

const updateSortOrder = () => {
  detailFlatList.value.forEach((item, index) => {
    item.sortorder = index + 1;
  });
};

const handleCurrentNodeChange = (row?: BomDetailItem) => {
  if (!row) return;
  currentParentNodeKey.value = row.nodekey || ROOT_NODE_KEY;
};

const setCurrentParent = (row: BomDetailItem) => {
  currentParentNodeKey.value = row.nodekey;
  ElMessage.success(`已切换父级到 ${row.materialname}`);
};

const handleRemoveNode = (row: BomDetailItem) => {
  ElMessageBox.confirm(`确认删除【${row.materialname}】及其子节点吗？`, "提示", {
    type: "warning",
  })
    .then(() => {
      removeNodeCascade(row.nodekey);
      if (currentParentNodeKey.value === row.nodekey) {
        currentParentNodeKey.value = ROOT_NODE_KEY;
      }
    })
    .catch(() => undefined);
};

const removeNodeCascade = (nodeKey: string) => {
  const queue = [nodeKey];
  const removed = new Set<string>();
  while (queue.length) {
    const key = queue.shift()!;
    removed.add(key);
    detailFlatList.value
      .filter((item) => item.parentnodekey === key)
      .forEach((child) => queue.push(child.nodekey));
  }
  detailFlatList.value = detailFlatList.value.filter((item) => !removed.has(item.nodekey));
};

const openProcessRouteDialog = () => {
  fetchProcessRouteList();
  processRouteDialogVisible.value = true;
};

const fetchProcessRouteList = async () => {
  const params = {
    process_routenameorcode: processRouteQuery.keyword || undefined,
    status: processRouteQuery.status ?? 0,
    pageindex: processRoutePager.page,
    pagesize: processRoutePager.size,
  };
  const { data } = await https.Reads.get("/AManufacturing_process/AProcess_routeShow", { params });
  if (data?.code === 1 || data?.Code === 1) {
    processRouteRows.value = data.data || data.Data || [];
    processRoutePager.total = data.totalCount || data.TotalCount || processRouteRows.value.length;
  }
};

const resetProcessRouteQuery = () => {
  processRouteQuery.keyword = "";
  processRouteQuery.status = 0;
  fetchProcessRouteList();
};

const handleProcessRouteSizeChange = (size: number) => {
  processRoutePager.size = size;
  processRoutePager.page = 1;
  fetchProcessRouteList();
};

const handleProcessRoutePageChange = (page: number) => {
  processRoutePager.page = page;
  fetchProcessRouteList();
};

const handleConfirmProcessRoute = () => {
  const row = processRouteRows.value.find((item) => item.id === selectedProcessRouteId.value);
  if (!row) {
    ElMessage.warning("请选择一条工艺路线");
    return;
  }
  selectedProcessRoute.value = row;
  formModel.process_routeid = row.id;
  processRouteDialogVisible.value = false;
};

const fetchProcessRouteById = async (id: number) => {
  const params = { pageindex: 1, pagesize: 100, process_routenameorcode: "" };
  const { data } = await https.Reads.get("/AManufacturing_process/AProcess_routeShow", { params });
  if (data?.code === 1) {
    const hit = (data.data || []).find((item: any) => item.id === id);
    if (hit) {
      selectedProcessRoute.value = hit;
      selectedProcessRouteId.value = id;
    }
  }
};

const buildRequestDetails = () =>
  detailFlatList.value.map((item) => ({
    materialid: item.materialid,
    materialcode: item.materialcode,
    materialname: item.materialname,
    specification: item.specification,
    unit: item.unit,
    quantity: item.quantity,
    lossrate: item.lossrate,
    sortorder: item.sortorder,
    remark: item.remark || "",
    nodetype: item.nodetype,
    nodekey: item.nodekey,
    parentnodekey: item.parentnodekey || ROOT_NODE_KEY,
  }));

const handleSubmit = async () => {
  if (!formRef.value) return;
  await formRef.value.validate(async (valid) => {
    if (!valid) return;
    if (!detailFlatList.value.length) {
      ElMessage.warning("请至少添加一个子产品或物料");
      return;
    }
    submitting.value = true;
    try {
      const payload = {
        id: isEdit.value ? bomId.value : 0,
        bomcode: formModel.bomcode,
        bomname: formModel.bomname,
        productid: formModel.productid,
        productcode: formModel.productcode,
        productname: formModel.productname,
        version: formModel.version || "",
        bomstate: formModel.bomstate,
        bomdes: formModel.bomdes || "",
        process_routeid: formModel.process_routeid,
        details: buildRequestDetails(),
      };
      const url = isEdit.value ? "/Bom/BomUpdate" : "/Bom/BomAdd";
      const method = isEdit.value ? "put" : "post";
      const { data } = await https.Writes[method](url, payload);
      if (data.code === 1) {
        ElMessage.success(data.msg || "保存成功");
        router.push("/BomList");
      } else {
        throw new Error(data.msg || "保存失败");
      }
    } catch (error: any) {
      ElMessage.error(error?.message || "保存失败");
    } finally {
      submitting.value = false;
    }
  });
};

const handleClose = () => {
  router.push("/BomList");
};

const loadBomData = async (id: number) => {
  detailLoading.value = true;
  try {
    const [bomRes, detailRes] = await Promise.all([
      https.Reads.get("/Bom/BomGetList", { params: { pageindex: 1, pagesize: 1000 } }),
      https.Reads.get("/Bom/BomGetDetailList", { params: { bomid: id, pageindex: 1, pagesize: 1000 } }),
    ]);
    if (bomRes.data.code === 1) {
      const hit = (bomRes.data.data || []).find((item: any) => item.id === id);
      if (hit) {
        formModel.bomcode = hit.bomcode;
        formModel.bomname = hit.bomname;
        formModel.productid = hit.productid;
        formModel.productcode = hit.productcode;
        formModel.productname = hit.productname;
        formModel.version = hit.version || "";
        formModel.bomstate = hit.bomstate;
        formModel.bomdes = hit.bomdes || "";
        formModel.process_routeid = hit.process_routeid || 0;
        if (formModel.process_routeid) {
          fetchProcessRouteById(formModel.process_routeid);
        }
      }
    }
    if (detailRes.data.code === 1) {
      detailFlatList.value = (detailRes.data.data || []).map((item: any) => ({
        materialid: item.materialid,
        materialcode: item.materialcode,
        materialname: item.materialname,
        specification: item.specification || "",
        unit: item.unit || "",
        quantity: item.quantity,
        lossrate: item.lossrate,
        sortorder: item.sortorder,
        remark: item.remark || "",
        nodetype: item.nodetype || 2,
        nodekey: item.nodekey || createNodeKey(),
        parentnodekey: item.parentnodekey || ROOT_NODE_KEY,
      }));
    }
  } finally {
    detailLoading.value = false;
  }
};

onMounted(() => {
  if (systemCodeAuto.value) {
    formModel.bomcode = generateAutoCode();
  }
  const id = route.query.id;
  if (id) {
    isEdit.value = true;
    bomId.value = Number(id);
    loadBomData(bomId.value);
  }
});

watch(
  () => selectedProcessRoute.value?.process_routecode,
  code => {
    if (code) {
      resetRouteMaterialFilter();
      clearProcessRouteMaterials();
      processRouteSelection.value = [];
      fetchProcessSteps(code);
      fetchProcessRouteMaterials(code);
    } else {
      processSteps.value = [];
      activeProcessNodeCode.value = "";
      activeProcessNodeId.value = null;
      clearProcessRouteMaterials();
      processRouteSelection.value = [];
    }
  }
);
</script>

<style scoped>
.bom-add-page {
  padding: 16px;
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.bom-breadcrumb-card,
.bom-main-card {
  width: 100%;
}

.bom-title {
  margin-bottom: 16px;
  font-weight: 600;
}

.bom-form {
  margin-bottom: 12px;
}

.bom-section {
  margin-top: 24px;
}

.section-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 12px;
}

.section-title {
  font-weight: 600;
  margin-right: 12px;
}

.section-actions {
  display: flex;
  gap: 8px;
}

.dialog-filter {
  margin-bottom: 12px;
}

.footer-actions {
  margin-top: 24px;
  text-align: right;
}

.process-route-steps-wrapper {
  margin-top: 16px;
}

.process-route-steps {
  display: flex;
  gap: 12px;
  overflow-x: auto;
  padding-bottom: 8px;
}

.process-route-step {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 16px;
  border-radius: 12px;
  background: #f5f7fb;
  cursor: pointer;
  border: 1px solid transparent;
  transition: all 0.2s ease;
  min-width: 180px;
}

.process-route-step:hover {
  border-color: #d5ddff;
}

.process-route-step.is-active {
  background: rgba(58, 122, 254, 0.08);
  border-color: #3a7afe;
}

.process-route-step .step-index {
  width: 32px;
  height: 32px;
  border-radius: 50%;
  background: #3a7afe;
  color: #fff;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-weight: 600;
}

.process-route-step.is-active .step-index {
  background: linear-gradient(125deg, #3a7afe, #7c5cfa);
}

.step-meta {
  display: flex;
  flex-direction: column;
}

.step-name {
  margin: 0;
  font-weight: 600;
  color: #2c3e50;
}

.step-desc {
  color: #909399;
}

.process-route-filter-bar {
  margin: 16px 0;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
  gap: 12px;
  align-items: center;
}

.process-route-toolbar {
  display: flex;
  justify-content: flex-end;
  gap: 12px;
  margin-bottom: 12px;
}

.process-route-table-card {
  margin-top: 8px;
}

.process-route-table :deep(.el-table__body-wrapper) {
  font-size: 13px;
}
</style>

